package com.yunxin.core.application.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.yunxin.common.exception.BusinessException;
import com.yunxin.common.result.PageResult;
import com.yunxin.common.utils.JacksonUtils;
import com.yunxin.core.application.assembler.ProductAssembler;
import com.yunxin.core.application.command.product.ProductMorePageCommand;
import com.yunxin.core.application.dto.order.PidAndTimeDTO;
import com.yunxin.core.application.dto.product.ProductBusinessSceneDTO;
import com.yunxin.core.application.dto.product.ProductInfoDTO;
import com.yunxin.core.application.dto.product.ProductMoreSimpleInfoDTO;
import com.yunxin.core.application.service.ProductQueryGatewayService;
import com.yunxin.core.domain.external.channel.ChannelProhibitProductService;
import com.yunxin.core.domain.external.merchant.MerchantExternalService;
import com.yunxin.core.domain.external.merchant.MerchantList;
import com.yunxin.core.domain.external.order.OrderExternalService;
import com.yunxin.core.dto.ApiConfigWecom;
import com.yunxin.core.infra.common.product.enums.ProductAbutmentTypeEnum;
import com.yunxin.core.infra.common.product.enums.ProductBusinessSceneEnum;
import com.yunxin.core.infra.persistence.entity.channel.ChannelProhibitProduct;
import com.yunxin.core.infra.persistence.entity.channel.ChannelPromotionDO;
import com.yunxin.core.infra.persistence.entity.product.ProductThrowInConfigDO;
import com.yunxin.core.infra.persistence.entity.product.query.condition.ProductMorePageCondition;
import com.yunxin.core.infra.persistence.entity.product.query.result.ProductInfoResult;
import com.yunxin.core.infra.persistence.entity.product.query.result.ProductMoreSimpleInfoResult;
import com.yunxin.core.infra.persistence.mapper.channel.ChannelPromotionExtendMapper;
import com.yunxin.core.infra.persistence.mapper.product.ProductInfoExtendMapper;
import com.yunxin.core.infra.persistence.mapper.product.ProductThrowInConfigExtendMapper;
import com.yunxin.core.utils.infra.common.constant.CoreResultCode;
import com.yunxin.core.utils.infra.utils.DateUtils;
import com.yunxin.core.utils.infra.utils.PageQueryUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zero°
 * @since 2023-06-08
 */
@Service
@RequiredArgsConstructor
public class ProductQueryGatewayServiceImpl implements ProductQueryGatewayService {

    private final ProductInfoExtendMapper productInfoExtendMapper;

    private final ProductThrowInConfigExtendMapper productThrowInConfigExtendMapper;

    private final MerchantExternalService merchantExternalService;

    private final OrderExternalService orderExternalService;

    private final ProductAssembler productAssembler;

    private final ChannelProhibitProductService channelProhibitProductService;


    @Override
    public ProductBusinessSceneDTO getProductBusinessScene(Long productId) {
        ProductThrowInConfigDO productThrowInConfigDO = productThrowInConfigExtendMapper.selectByProductId(productId);
        if (Objects.isNull(productThrowInConfigDO)) {
            throw new BusinessException(CoreResultCode.PRODUCT_CONFIG_ERROR);
        }
        ProductBusinessSceneDTO productBusinessSceneDTO = new ProductBusinessSceneDTO();
        // 对接方式 1.自营 2.h5 --> 业务场景
        if (ProductAbutmentTypeEnum.H5.getValue().equals(productThrowInConfigDO.getAbutmentType())) {
            productBusinessSceneDTO.setBusinessScene(ProductBusinessSceneEnum.UV.getValue());
        } else {
            productBusinessSceneDTO.setBusinessScene(ProductBusinessSceneEnum.FROM.getValue());
        }
        return productBusinessSceneDTO;
    }


    @Override
    public ProductInfoDTO getProductInfo(Long productId) {
        ProductInfoResult result = productInfoExtendMapper.selectProductInfoResultByProductId(productId);
        ProductInfoDTO dto = productAssembler.toProductInfoDTO(result);
        Set<Long> merchantIds = new HashSet<>();
        merchantIds.add(result.getMerchantId());
        Map<Long, MerchantList> merchantListResultMap = merchantExternalService.listMerchantByIds(merchantIds).stream().collect(Collectors.toMap(MerchantList::getId, Function.identity()));
        MerchantList merchantList = merchantListResultMap.get(result.getMerchantId());
        Optional.ofNullable(merchantList).ifPresent(m -> dto.setMerchantName(m.getMerchantName()));
        dto.setMerchantId(result.getMerchantId());
        return dto;
    }

    @Override
    public PageResult<ProductMoreSimpleInfoDTO> moreProductPage(ProductMorePageCommand command) {
        ProductMorePageCondition condition = new ProductMorePageCondition();
        condition.setProductIds(command.getProductIds());
        List<PidAndTimeDTO> pidAndTimeDTOS = orderExternalService.selectPidAndTimeByUserCode(command.getUserCode());
        Collections.sort(pidAndTimeDTOS);
        Collections.reverse(pidAndTimeDTOS);
        int j = 100;
        for (PidAndTimeDTO pidAndTimeDTO : pidAndTimeDTOS) {
            pidAndTimeDTO.setSeq(j++);
        }
        Map<Long, PidAndTimeDTO> timeDTOMap = pidAndTimeDTOS.stream().collect(Collectors.toMap(PidAndTimeDTO::getProductId, Function.identity(),(a,b) -> {
            if (a.getUpdateTime().getTime() > b.getUpdateTime().getTime()) {
                return a;
            } else {
                return b;
            }
        }));

        long total = productInfoExtendMapper.countMoreProductPage(condition);
//        long loginTotal = productInfoExtendMapper.countMoreUvProductPage(condition);
//        long total = uvTotal + loginTotal;
        if (total == 0) {
            return PageResult.success(Collections.emptyList(), total);
        }
        condition.setOffset(PageQueryUtils.X.getOffset(command.getPageNum(), command.getPageSize()));
        condition.setPageSize(command.getPageSize());
        List<ProductMoreSimpleInfoResult> results = productInfoExtendMapper.moreProductPage(condition);

//        List<ProductMoreSimpleInfoResult> loginResults = productInfoExtendMapper.loginProduct(condition);
//        results.addAll(loginResults);
//        results.stream()
        List<ChannelProhibitProduct> channelProhibitProduct = channelProhibitProductService.getChannelProhibitProductByCode(command.getChannelCode());

        List<Long> prohibitProductIds = channelProhibitProduct.stream().map(ChannelProhibitProduct::getProductId).toList();

        List<ProductMoreSimpleInfoDTO> dtoList = results.stream().filter(it -> {

                    Integer placementPeriodType = it.getPlacementPeriodType();
                    if (placementPeriodType == 2) {
                        JSONArray array = JSONUtil.parseArray(it.getPlacementPeriod());
                        DateTime date = DateUtil.date();
                        String dayStr = date.toString(DatePattern.NORM_DATE_FORMAT) + " ";
                        for (int i = 0; i < array.size(); i++) {
                            JSONObject entries = array.getJSONObject(i);
                            String startTimeStr = entries.getStr("startTime");
                            String endTimeStr = entries.getStr("endTime");
                            DateTime startTime = DateUtil.parse(dayStr + startTimeStr + ":00");
                            DateTime endTime = DateUtil.parse(dayStr + endTimeStr + ":00");
                            if (date.getTime() > startTime.getTime() && date.getTime() < endTime.getTime()) {
                                return true;
                            }
                        }
                        return false;
                    }
                    return true;
                }).filter(it->{
                    String limitDay = it.getLimitDay();
                    if (StrUtil.isEmpty(limitDay)) {
                        return true;
                    }
                    String week = DateUtils.X.getTodayWeek(LocalDateTime.now());
                    return limitDay.contains(week);
                }).filter(it -> !prohibitProductIds.contains(it.getProductId()))
                .map(x -> {
                    ProductMoreSimpleInfoDTO dto = new ProductMoreSimpleInfoDTO();
                    dto.setProductId(x.getProductId());
                    dto.setProductName(x.getProductName());
                    dto.setProductImage(x.getProductImage());
                    dto.setHighestBorrowableAmount(x.getHighestBorrowableAmount());
                    dto.setProductLabelingList(List.of(x.getProductLabeling().split(",")));
                    dto.setSellingPoint(x.getSellingPoint());
                    dto.setReferenceRate(JacksonUtils.X.parse(x.getReferenceRate(), ProductMoreSimpleInfoDTO.ReferenceRate.class));
                    dto.setUserProtocolList(JacksonUtils.X.parse(x.getUserProtocol(), new TypeReference<>() {}));
                    return dto;
                }).toList();


        List<ProductMoreSimpleInfoDTO> sort = CollUtil.sort(new ArrayList<>(dtoList), ((o1, o2) -> {

            PidAndTimeDTO o1Time = timeDTOMap.get(o1.getProductId());
            PidAndTimeDTO o2Time = timeDTOMap.get(o2.getProductId());
            int o1Seq = -1;
            if (Objects.nonNull(o1Time)) {
                o1Seq = o1Time.getSeq();
            }
            int o2Seq = -1;
            if (Objects.nonNull(o2Time)) {
                o2Seq = o2Time.getSeq();
            }
            return o1Seq - o2Seq;
        }));

        return PageResult.success(sort, total);
    }


    /**
     * 根据产品id获取企微配置信息
     *
     * @param productId
     * @return
     */
    @Override
    public ApiConfigWecom getWeComApiConfig(Long productId) {
        return productInfoExtendMapper.getWeComApiConfig(productId);
    }
}
